package cn.sirun.com.fca.account.fragment;

import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.hardware.Camera;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.tencent.cloud.iov.util.FileUtils;
import com.tencent.cloud.iov.util.ResourcesUtils;
import com.tencent.cloud.iov.util.ViewStateUtils;
import com.tencent.cloud.uikit.utils.DialogUtils;
import com.tencent.cloud.uikit.utils.PermissionUtils;
import com.tencent.mars.xlog.Log;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;

import cn.sirun.com.fca.account.R;
import cn.sirun.com.fca.account.constant.RequestParamConst;
import cn.sirun.com.fca.account.listener.OnBackPressedListener;
import cn.sirun.com.fca.account.uitl.AccountViewUtils;
import cn.sirun.com.fca.account.widget.CameraPreview;
import pub.devrel.easypermissions.EasyPermissions;

/**
 * 拍照Fragment
 */
public class CameraFragment extends Fragment implements View.OnClickListener,
        OnBackPressedListener, EasyPermissions.PermissionCallbacks {

    private static final String TAG = CameraFragment.class.getSimpleName();

    private static final int REQUEST_CAMERA_PERMISSION = 1;

    private FrameLayout mCameraLayout;

    private View mCropView;

    private CameraPreview mCameraPreview;

    private OnCameraListener mCameraListener;

    private TextView mCameraTitle;

    private RelativeLayout mCameraContainerRL;

    private ImageView mTakePhotoIV;

    private String mTitle = "";

    private RequestParamConst.PictureTypeEnum mPictureType =
            RequestParamConst.PictureTypeEnum.IDENTITY_CARD;

    private AsyncTask<byte[], Void, String> mTakePhotoPostTask;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return inflater.inflate(R.layout.camera_fragment, container, false);
    }

    @Override
    public void onViewCreated(final View view, Bundle savedInstanceState) {
        mCameraLayout = view.findViewById(R.id.fl_camera_container);
        mCropView = view.findViewById(R.id.iv_camera_crop);
        mCameraTitle = view.findViewById(R.id.tv_camera_title);
        mCameraContainerRL = view.findViewById(R.id.rl_camera_container);
        mTakePhotoIV = view.findViewById(R.id.btn_picture);
        mTakePhotoIV.setOnClickListener(this);
        if (RequestParamConst.PictureTypeEnum.IDENTITY_CARD == mPictureType) {
            mTitle = getActivity().getString(R.string.upload_recognize_camera_aperture);
        } else {
            mTitle = getActivity().getString(R.string.upload_recognize_camera_aperture);
        }
        mCameraTitle.setText(mTitle);
        mCropView.post(new Runnable() {
            @Override
            public void run() {
                if (RequestParamConst.PictureTypeEnum.VEHICLE_LICENSE == mPictureType) {
//                    mCropView.setBackgroundResource(R.drawable.act_img_cam_frame);
                } else {
//                    mCropView.setBackgroundResource(R.drawable.act_img_cam_frame_id);
                }
            }
        });

        AccountViewUtils.adjustTitlePadding(mCameraTitle);
        ViewStateUtils.setUpViewPressState(mTakePhotoIV);

        initCameraView();
    }

    private void initCameraView() {
        if (!getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
            DialogUtils.showToast(getActivity(), "设备没有相机");
            onBackPressed();
            return;
        }

        if (!PermissionUtils.hasCameraPermissions(getContext())) {
            PermissionUtils.requestCameraPermissions(this);
            return;
        }

        mCameraPreview = new CameraPreview(getContext());
        mCameraLayout.addView(mCameraPreview);
    }

    @Override
    public void onResume() {
        super.onResume();
        startPreview();
    }

    @Override
    public void onPause() {
        super.onPause();
        if (null != mCameraPreview) {
            mCameraPreview.release();
        }
    }

    @Override
    public void onDestroy() {
        if (mTakePhotoPostTask != null) {
            mTakePhotoPostTask.cancel(true);
            mTakePhotoPostTask = null;
        }
        super.onDestroy();
    }

    @Override
    public void onClick(View view) {
        int id = view.getId();
        if (R.id.btn_picture == id) {
            takePhoto();
            setPictureBtnClickable(false);
        } else if (R.id.iv_camera_crop == id) {
            mCameraPreview.focus();
        }
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (!PermissionUtils.isSettingsPermissionRequest(requestCode)) {
            return;
        }
        if (PermissionUtils.hasCameraPermissions(getContext())) {
            initCameraView();
            startPreview();
            return;
        }
        DialogUtils.showToast(getActivity(), R.string.request_camera_permission_failed);
        onBackPressed();
    }

    public void startPreview() {
        if (mCameraPreview != null) {
            mCameraPreview.startPreview();
            mCropView.setVisibility(View.VISIBLE);
            setPictureBtnClickable(true);
        }
    }

    public void checkPermissionOrStartPreview() {
        if (!PermissionUtils.hasCameraPermissions(getContext())) {
            PermissionUtils.requestCameraPermissions(this);
            return;
        }

        startPreview();
    }

    private void takePhoto() {
        if (null == mCameraPreview) {
            handleTakePhotoFailed();
            return;
        }

        mCameraPreview.takePhoto(new Camera.PictureCallback() {
            @Override
            public void onPictureTaken(final byte[] data, Camera camera) {
                if (mTakePhotoPostTask != null) {
                    mTakePhotoPostTask.cancel(false);
                }
                mTakePhotoPostTask = new TakePhotoPostTask().execute(data);
            }
        });
    }

    public void setPictureType(RequestParamConst.PictureTypeEnum pictureType) {
        mPictureType = pictureType;
    }

    public void setCameraListener(OnCameraListener cameraListener) {
        mCameraListener = cameraListener;
    }

    @Override
    public boolean onBackPressed() {
        mCameraListener.onBackPressed();
        return true;
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    @Override
    public void onPermissionsGranted(int requestCode, @NonNull List<String> perms) {
        Log.d(TAG, "onPermissionsGranted: requestCode = [" + requestCode + "], perms = [" + perms + "]");
        initCameraView();
        startPreview();
    }

    @Override
    public void onPermissionsDenied(int requestCode, @NonNull List<String> perms) {
        Log.d(TAG, "onPermissionsDenied: requestCode = [" + requestCode + "], perms = [" + perms + "]");
        onBackPressed();
    }

    public interface OnCameraListener {

        /**
         * 图片拍照回调
         *
         * @param filePath 文件路径
         */
        void onTakePictureCallback(String filePath);

        /**
         * back键回调
         */
        void onBackPressed();
    }

    private void setPictureBtnClickable(boolean clickable) {
        mTakePhotoIV.setClickable(clickable);
    }

    private void handleTakePhotoFailed() {
        // 拍照失败
        setPictureBtnClickable(true);
        mCameraPreview.startPreview();
        DialogUtils.showToast(getActivity(), "拍照失败，请重试");
    }

    private class TakePhotoPostTask extends AsyncTask<byte[], Void, String> {

        @Override
        protected String doInBackground(byte[]... bytes) {
            FileOutputStream fos = null;
            BufferedOutputStream bos = null;

            try {
                byte[] data = bytes[0];

                Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
                int bitmapWidth = bitmap.getWidth();
                int bitmapHeight = bitmap.getHeight();

                Matrix matrix = new Matrix();
                matrix.postRotate(90);
                float left = ((float) mCameraContainerRL.getTop() -
                        (float) mCameraPreview.getTop()) /
                        (float) mCameraPreview.getHeight();
                float top = (float) mCropView.getLeft() /
                        (float) mCameraPreview.getWidth();
                float right = (float) mCameraContainerRL.getBottom() /
                        (float) mCameraPreview.getHeight();
                float bottom = (float) mCropView.getRight() /
                        (float) mCameraPreview.getWidth();

                // 截取采集区图片
                Bitmap cropBitmap = Bitmap.createBitmap(bitmap,
                        (int) (left * (float) bitmapWidth),
                        (int) (top * (float) bitmapHeight),
                        (int) ((right - left) * (float) bitmapWidth),
                        (int) ((bottom - top) * (float) bitmapHeight), matrix,
                        true);

                // 压缩图片
                String fileName = System.currentTimeMillis() + ".jpg";
                final File cropFile = new File(CameraFragment.this.getActivity()
                        .getExternalCacheDir(), fileName);

                fos = new FileOutputStream(cropFile);
                bos = new BufferedOutputStream(fos);
                cropBitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
                bos.flush();

                return cropFile.getAbsolutePath();
            } catch (FileNotFoundException e) {
                Log.e(TAG, "save picture failed", e);
            } catch (IOException e) {
                Log.e(TAG, "handle picture failed", e);
            } finally {
                FileUtils.close(bos);
                FileUtils.close(fos);
            }

            return null;
        }

        @Override
        protected void onPostExecute(String filePath) {
            if (!TextUtils.isEmpty(filePath)) {
                mCameraListener.onTakePictureCallback(filePath);
                mCameraPreview.release();
                mCropView.setVisibility(View.INVISIBLE);
            } else {
                handleTakePhotoFailed();
            }
        }
    }
}
